<?php
namespace App\Services\Impl;
use App\Services\ZhjyServiceInterface;
use Log;
use Illuminate\Support\Facades\Auth;
use App\Pojo\ResponsePojo;
use App\Constant\HttpStatus;
use Illuminate\Support\Facades\Http;
use App\Constant\ApiUrl;
use App\Utils\Utils;
use App\Library\ZhjyLibraryInterface;
use Illuminate\Support\Facades\Redis;
use PhpOffice\PhpSpreadsheet\IOFactory;
use App\Services\RepotsServiceInterFace;
use App\Exceptions\BusinessException;
final class ZhjyServiceImpl implements ZhjyServiceInterface{

    protected $apiUrl;
    protected $zhjyLibrary;
    private $refreshAttempts = 0;
    private $headers = [
        'Content-Type' => 'application/json',
        'User-Agent' => ''
    ];
    private const MAX_REFRESH_ATTEMPTS = 3;
    private $repotsService;

    

    public function __construct(ApiUrl $apiUrl, ZhjyLibraryInterface $zhjyLibrary, RepotsServiceInterFace $repotsService)
    {
        $this->apiUrl = $apiUrl;
        $this->zhjyLibrary = $zhjyLibrary;
        $this->headers['User-Agent'] = Utils::generateRandomHeaders()['User-Agent'];
        $this->repotsService = $repotsService;
    }

    /**
     * 获取实习Id
     * @param mixed $token
     */
    public function getStudentPlanId($token){
        $currentHeader = [
            "Authorization"=> $token,
        ];
        $mergedHeaders = array_merge($this->headers, $currentHeader);
        Log ::debug( '请求头');
        Log ::debug( $mergedHeaders);
        $response = Http::withHeaders($mergedHeaders)->get($this->apiUrl->getStudentPlanId());
        if ($response->successful()) {
            return $response->json()['data']['autonomyPlan']['id'];
        }
    }
    public function login($request, $credentials){
        $loginBody = [
            "appLogin"=>"true",
            "loginAccount"=> $credentials["dawn_zhjyUser"],
            "password"=> $credentials["dawn_zhjyPassword"],
            "appUserId"=>"",
            "loginUserType"=>$credentials["dawn_identity"],
            "enrollmentYear"=>$credentials["dawn_classOlder"]
        ];
        $response = Http::withHeaders($this->headers)->post($this->apiUrl->getLoginUrl(), $loginBody);
        // 检查请求是否成功
        if ($response->successful()) {
            // 获取响应的 JSON 数据
            $message = $response->json();
            if($message['code'] == 500){
                return ResponsePojo::error($message['code'],$message['msg']);
            }
            $data = $response->json()['data'];
                // 获取实习Id
                $token = 'Bearer '.$data['token'];
                Log::info($token);
                $autonomyPlanId = $this->getStudentPlanId($token);

                $zhjy_data = [
                    "userId" =>  $data['userId'], // 用户id 
                    "autonomyPlanId" => $autonomyPlanId, // 实习Id 
                    "dawn_zhjyUser" =>  $credentials["dawn_zhjyUser"], // 登录账号 
                    "avatar" =>  $data['avatar'], // 用户id 
                    "password" =>  $credentials["dawn_zhjyPassword"], // 登录密码 
                    "email" =>  $data['email'], // 用户id 
                    "username" =>  $data['username'],// 身份证 
                    "nickName" =>  $data['nickName'],// 姓名 
                    "token" =>  $token, // 令牌
                    "schoolName" =>  $data['schoolName'], // 学校
                    "sex" =>  $data['sex'], // 性别
                    "phone" =>  $data['phone'], // 电话
                    "userType" =>  $data['userType'], // 身份
                    "studentNo" =>  $data['studentNo'], // 学号
                    "deptName" =>  $data['deptName'], // 班级
                    "enrollmentYear" =>  $data['enrollmentYear']// 应届数
                ];
                Log::info("========================我存了UserId======================");
                Log::info($zhjy_data);
                Log::info("========================我存了UserId======================");
                // 添加默认过期时间（7200秒 = 2小时）
                $expiryTime = env('ExpiryTime', 7200);
                Redis::setex('userId:'.Auth::id(), $expiryTime, json_encode($zhjy_data)); // 将平台信息存入缓存
                // 信息入库， c存在则更新
                $result = $this->zhjyLibrary->bindLogin($zhjy_data);
                if ($result) {
                    return ResponsePojo::success(HttpStatus::OK,HttpStatus::getStatusMessage(HttpStatus::OK));
                }else{
                    return ResponsePojo::success(HttpStatus::EXISTIMG_USER,HttpStatus::getStatusMessage(HttpStatus::EXISTIMG_USER));
                }
        } else {
            // 处理请求失败的情况
            $statusCode = $response->status();
            Log::info('请求超时');
            return ResponsePojo::error(HttpStatus::INTERNAL_SERVER_ERROR,HttpStatus::getStatusMessage(HttpStatus::INTERNAL_SERVER_ERROR));
        }
    }

    public function findZhjyStatus() {
        $result = $this->zhjyLibrary->findZhjyStatus();
        if ($result!=null) {
            $dawn_zhjyStatus = $result['dawn_zhjyStatus'];
            if ($dawn_zhjyStatus == 0) {
                return ResponsePojo::success(HttpStatus::OK,HttpStatus::getStatusMessage(HttpStatus::OK), $result);
            }else{
               
                return ResponsePojo::error(HttpStatus::EXISTIMG_USER,HttpStatus::getStatusMessage(HttpStatus::EXISTIMG_USER), $result);
            }
        }
        return ResponsePojo::success(HttpStatus::OK,HttpStatus::getStatusMessage(HttpStatus::NOT_FOUND), $result);

        

    }

    /**
     * 获取平台令牌方法
     * @return void
     */
    public function getZhjyToken(){
        $userId = Auth::id();
        $jsonData = Redis::get("userId:{$userId}");
        Log::info($jsonData);
        if(empty($jsonData)){
            // 令牌为空，获取令牌 
            // 根据id获取当前用户，获取账号密码进行登录
            Log::info('递归拿刷新token');
            
            // 检查递归次数
            if ($this->refreshAttempts >= self::MAX_REFRESH_ATTEMPTS) {
                Log::error(sprintf('刷新token达到最大尝试次数: %d次', self::MAX_REFRESH_ATTEMPTS));
                throw new \Exception('刷新token失败，已达到最大尝试次数');
            }
            $this->refreshAttempts++;
            return $this->refreshToken();
        }
        // 重置计数器
        $this->refreshAttempts = 0;
        $data = json_decode($jsonData, true);
        return $data;
    }
    /**
     * 刷新token
     */
    public function refreshToken(){
        $result = $this->zhjyLibrary->findZhjyStatus();
        $loginBody = [
            "dawn_zhjyUser"=> $result["dawn_zhjyUser"],
            "dawn_zhjyPassword"=> $result["dawn_zhjyPassword"],
            "dawn_identity"=>$result["dawn_zhjyidEntity"],
            "dawn_classOlder"=>$result["dawn_zhjyEnrollmentYear"]
        ];
        $this->login(null,$loginBody);
    }

    public function register($credentials){
       
        
    }


    public function logout($request){

    }


    /**
     * 获取令牌、用户id、实习id
     * @param mixed $request
     * @return void
     */
    public function getRedisZhjyInfo($head){
        $userId = Auth::id();
        Log::info('缓存Key:');
        Log::info($head.":{$userId}");
        $jsonData = Redis::get($head.":{$userId}");
        Log::info($head.":{$userId}");
        $data = json_decode($jsonData, true);
        return $data;        
    }


    public function getDawnLogs($queryDate)
    {
        // 定义最大递归尝试次数
        $maxAttempts = 3;
        static $attemptCount = 0;
    
        // 如果日志记录有缓存
        $logRows = $this->getRedisZhjyInfo($queryDate.'logRows');
        if (empty($logRows)) {
            // 如果没有缓存，则从平台中获取
            $data = $this->getRedisZhjyInfo('userId');
            $token = $data['token'];
            $autonomyId = $data['autonomyPlanId'];
            $userId = $data['userId'];
    
            $currentHeader = [
                "Authorization" => $token,
            ];
            $mergedHeaders = array_merge($this->headers, $currentHeader);
            $response = Http::withHeaders($mergedHeaders)
                ->get($this->apiUrl->getLogs($autonomyId, $userId, $queryDate));
    
            $responseArray = $response->json();
    
            // 检查是否需要刷新令牌
            if ($responseArray['code'] == 401) {
                Log::info('用户未登录或登录已过期');
    
                // 增加尝试次数
                $attemptCount++;
                if ($attemptCount > $maxAttempts) {
                    Log::error('刷新令牌失败，已达到最大尝试次数');
                    throw new \Exception('无法获取打卡记录：令牌刷新失败');
                }
    
                // 刷新令牌并重新调用
                $this->refreshToken();
                return $this->getDawnLogs($queryDate);
            }
    
            // 处理返回数据
            if (isset($responseArray['rows'])) {
                foreach ($responseArray['rows'] as &$row) {
                    if (isset($row['filePath'])) {
                        $row['filePath'] = ApiUrl::$baseApiUrl . $row['filePath'];
                    }
                }
                // 释放引用
                unset($row);
            }
    
            // 缓存时间为10秒
            Redis::setex($queryDate.'logRows:' . Auth::id(), 60, json_encode($responseArray)); // 将平台打卡信息存入缓存
    
            // 重置递归计数器
            $attemptCount = 0;
    
            return $responseArray;
        } else {
            // 重置递归计数器
            Log::error('获取缓存的打卡记录'.$queryDate.'logRows');
            $attemptCount = 0;
    
            return $logRows;
        }
    }

    public function uploadFile($currentHeader, $file){
            // 以二进制方式读取文件内容
            try{
                $fileContent = fopen($file->getPathname(), 'rb');
                        
            Log::info($fileContent);

            $response = Http::withHeaders($currentHeader)
                ->attach(
                    'file',
                    $fileContent,
                    $file->getClientOriginalName(),
                    ['Content-Type' => 'application/octet-stream']
                )
                ->post($this->apiUrl->getUploadFileUrl());

            // 关闭文件句柄
            fclose($fileContent);
            if ($response->successful()) {
                return $response->json();
            } else {
                return ['message' => '文件上传失败', 'code' => 500];
            }
        } catch (\Exception $e) {
            return ['message' => '文件上传失败', 'code' => 500];
        }
    }


    public function uploadZhjyFileUrl($request)
    {
        if ($request->hasFile('files')) {
            foreach ($request->file('files') as $file) {
                
                $data = $this->getRedisZhjyInfo('userId');
                $token = $data['token'];
                $currentHeader = [
                    "Authorization" => $token,
                ];
                return $this->uploadFile($currentHeader, $file);
                
                // // 以二进制方式读取文件内容
                // $fileContent = fopen($file->getPathname(), 'rb');
               
                // Log::info($fileContent);
                
                // $response = Http::withHeaders($currentHeader)
                //     ->attach(
                //         'file',
                //         $fileContent,
                //         $file->getClientOriginalName(),
                //         ['Content-Type' => 'application/octet-stream']
                //     )
                //     ->post($this->apiUrl->getUploadFileUrl());
                
                // // 关闭文件句柄
                // fclose($fileContent);
                
                // if ($response->successful()) {
                //     return $response;
                // } else {
                //     return response()->json(['message' => '文件上传失败', 'status' => $response->status()], 500);
                // }
            }
        }
    }

    /**
     * 解析Excel文件
     * @param $file 上传的Excel文件
     * @return array 解析后的数据
     */
    public function parseExcel($file, $credentials)
    {
        // 获取文件后缀
        $extension = $file->getClientOriginalExtension();
        // 定义允许的文件类型
        $allowedFileExtensions = ['xls', 'xlsx'];
        // 判断是否为Excel文件
        $isExcel = in_array(strtolower($extension), $allowedFileExtensions);
        if (!$isExcel) {
            Log::error('正常保存文件');
            return;
        }
        try {
            // 使用 Laravel Excel 读取文件
            $spreadsheet = IOFactory::load($file->getPathname());
            $worksheet = $spreadsheet->getActiveSheet();
            
            // 获取所有数据
            $data = [];
            foreach ($worksheet->getRowIterator(2) as $row) {
                $rowData = [];
                $cellIterator = $row->getCellIterator();
                $cellIterator->setIterateOnlyExistingCells(false);
                
                foreach ($cellIterator as $cell) {
                    $rowData[] = $cell->getValue();
                }
                $data[] = $rowData;
            }

            $itemDetail = [];
            foreach($data as $item){
                $itemDetail[] = [
                    'recordType' => Utils::convertRecordType($item[0]),
                    'todaySummary' => $item[1],
                    'nextSummary' => $item[2],
                    'feedback' => $item[3],
                    'filePath' => $credentials['file_path'],
                    'fileName' => $credentials['file_name'],
                    'selfEvaluate' => Utils::convertSelfEvaluate($item[4])
                ];
            }

            $result = $this->repotsService->insertReport($itemDetail);
            $messsage = '插入报告成功: ' . $result['successCount'] . '条，失败: ' . $result['failCount'] . '条，总计: ' . $result['totalCount'] . '条';
            return $messsage;

        } catch (\Exception $e) {
            Log::error('解析Excel文件失败: ' . $e->getMessage());
            Log::error('正常保存文件');
            return;
        }
    }




    /**
     * 存到本地
     */
    public function uploadLocalFileUrl($request){
        $uploadedFiles = [];
        if ($request->hasFile('files')) {
            foreach ($request->file('files') as $file) {

                // 获取当前日期
                $date = date('Y-m-d'); // 格式：2025-04-11
    
                // 检查文件类型
                $isImage = strpos($file->getMimeType(), 'image') === 0;

                // 检查文件类型
                $isImage = strpos($file->getMimeType(), 'image') === 0;

                $fileType = $isImage ? 'image' : 'file';
               
                
                // 设置存储路径
                $folder = $isImage ? "uploads/images/{$date}" : "uploads/files/{$date}";
    
                // 生成唯一文件名
                $uniqueFileName = uniqid() . '_' . $file->getClientOriginalName();
    
                // 存储文件到对应的目录
                $path = $file->storeAs($folder, $uniqueFileName, 'public'); // 存储到 public/uploads/images 或 public/uploads/files
                
                
                $credentials = [
                    'user_id' => Auth::id(),
                    'file_name' => $file->getClientOriginalName(),
                    'file_path' => $path,
                    'file_type' => $fileType,
                    'file_size' => $file->getSize(),
                    'storage_type' => 'local',
                    'mime_type' => $file->getMimeType(),
                    'file_hash' => md5($file->getPathname()),
                    'status' => 1,
                    'created_at' => now(),
                    'updated_at' => now()
                ];

                $message = '';
                if ($fileType == 'file'){
                    // 如果是图片，则调用解析方法
                   $message = $this->parseExcel($file, $credentials);
                }

                $fileId = $this->zhjyLibrary->saveZhjyFile($credentials); // 保存文件信息

                // 保存文件信息
                $uploadedFiles[] = [
                    'code' => 200,
                    'fileName' => $file->getClientOriginalName(),
                    'fileSize' => $file->getSize(),
                    'fileType' => $fileType,
                    'file_hash' => $fileId->file_hash,
                    'id' => $fileId->id,
                    'url' => asset('storage/' . $path),
                    'create_at' => $fileId->created_at,
                ];
            }
        }
        return ResponsePojo::success(HttpStatus::OK, empty($message) ? HttpStatus::getStatusMessage(HttpStatus::OK) : $message, $uploadedFiles);
    }


    public function saveZhjyClock($credentials){
        $clockAddress = $credentials['clockAddress'];
        $clockContent = $credentials['clockContent'];
        $filePath = $credentials['filePath'];
        $fileIds = $credentials['fileIds'];
        $orgUrls = $credentials['orgUrls'];
        
        $data = $this->getRedisZhjyInfo('userId');
        Log::info($data);
        $token = $data['token'];
        $userId = $data['userId'];
        $autonomyPlanId = $data['autonomyPlanId'];
        $nickName = $data['nickName'];

        $currentHeader = [
            "Authorization" => $token,
        ];

        $addBody = [
            "autonomyId"=> $autonomyPlanId,
            "userId"=> $userId,
            "nickName"=> $nickName,
            "clockAddress"=> $clockAddress,
            "fileId"=> $fileIds,
            "clockTime"=> Utils::getFormatted_datetime_now(),
            "clockType"=> '签到',
            "clockContent"=> $clockContent
        ];
        Log::info($addBody);

        $mergedHeaders = array_merge($this->headers, $currentHeader);

        $response = Http::withHeaders($mergedHeaders)
            ->post($this->apiUrl->getDawnUrl(), $addBody);

        $data = $response->json();
        if($data['code'] == 500){
            return ResponsePojo::error($data['code'],$data['msg'], $data['data']);
        }
        if($data['code'] == 200){
            Redis::del(Utils::getYMDDate().'logRows:' . Auth::id());
            return ResponsePojo::success(HttpStatus::OK,"打卡成功", $data['data']);
        }
        return ResponsePojo::error(HttpStatus::INTERNAL_SERVER_ERROR,HttpStatus::getStatusMessage(HttpStatus::INTERNAL_SERVER_ERROR));

    }   
    public function saveZhjyLog($credentials){

        function setRate($rate) {
            switch($rate) {
                case '1':
                    return '4';
                case '2':
                    return '1';
                case '3':
                    return '2';
                case '4':
                    return '3';
                default:
                    return '';
            }
        }
        function joinfilesId($credentials): string{
            $fileIds = [];
            
            if (!empty($credentials['fileList'])){
                // 文件列表不为空
                $fileList = $credentials['fileList'];
                foreach($fileList as $file){
                    $fileIds[] = $file['id'];
                }
            }
            if (!empty($credentials['imageList'])){
                // 图片列表不为空
                $imageList = $credentials['imageList'];
                foreach($imageList as $image){
                    $fileIds[] = $image['id'];
                }
            }
            
            // 将ID数组拼接成字符串，用逗号分隔
            return !empty($fileIds) ? implode(',', $fileIds) : '';
        }

        $logType = $credentials['logType'];
        $displayDate = $credentials['displayDate'];
        $weeklySummary = $credentials['weeklySummary'];
        $nextWeekPlan = $credentials['nextWeekPlan'];
        $feedback = $credentials['feedback'];
        $selfEvaluation = setRate($credentials['selfEvaluation']);
        $fileId = joinfilesId($credentials);

        $data = $this->getRedisZhjyInfo('userId');
        $token = $data['token'];
        $userId = $data['userId'];
        $autonomyPlanId = $data['autonomyPlanId'];
        $nickName = $data['nickName'];

        $currentHeader = [
            "Authorization" => $token,
        ];

        $logBody = [
            'recordType' => $logType, // 日志类型
            'recordTime' => $displayDate, // 日志时间
            'todaySummary' => $weeklySummary, // 今日总结
            'nextSummary' => $nextWeekPlan, // 下周计划
            'feedback' => $feedback, // 反馈
            'selfEvaluate' => $selfEvaluation, // 自评
            'userId' => $userId, // 用户id
            'nickName' => $nickName, // 姓名
            'fileId' => $fileId, // 文件id
            'autonomyId' => $autonomyPlanId, // 实习id
        ];
        Log::info($logBody);

        $mergedHeaders = array_merge($this->headers, $currentHeader);

        $response = Http::withHeaders($mergedHeaders)
            ->post($this->apiUrl->getLogUrl(), $logBody);

        $data = $response->json();
        Log::info($data);
        if($data['code'] == 500){
            return ResponsePojo::error($data['code'],$data['msg'], $data['data']);
        }
        if($data['code'] == 200){
            $logKey = 'log_rows:' . 1 . ':' . 10 . ':' .Auth::id();
            Redis::del($logKey);
            return ResponsePojo::success(HttpStatus::OK,"日志提交成功", $data['data']);
        }
       
    }   

    public function getLogRows($credentials){
        // 生成缓存key
        $cacheKey = 'log_rows:' . $credentials['pageNum'] . ':' . $credentials['pageSize'];
        
        // 尝试从Redis获取数据
        $cachedData = $this->getRedisZhjyInfo($cacheKey);
        if ($cachedData) {
            return ResponsePojo::success(HttpStatus::OK,HttpStatus::getStatusMessage(HttpStatus::OK), $cachedData);
        }
        Log::info('缓存中没有数据');
        // 如果日志记录有缓存
        $data = $this->getRedisZhjyInfo('userId');
        $token = $data['token'];
        $userId = $data['userId'];
        $autonomyPlanId = $data['autonomyPlanId'];

        $currentHeader = [
            "Authorization" => $token,
        ];

        $logBody = [
            'planId' => '',
            'autonomyId' => $autonomyPlanId, 
            'userId' => $userId, 
            'pageNum' => $credentials['pageNum'], 
            'pageSize' => $credentials['pageSize'],
        ];
        $mergedHeaders = array_merge($this->headers, $currentHeader);

        $response = Http::withHeaders($mergedHeaders)
            ->get($this->apiUrl->getLogListUrl($logBody['autonomyId'], $logBody['userId'], $logBody['pageNum'], $logBody['pageSize']));
            $data = $response->json();
            // Log::info($data);
            if($data['code'] == 500){
                return ResponsePojo::error($data['code'],$data['msg'], $data['data']);
            }
            if($data['code'] == 200){
                $rows = $data['rows'];
                $allDatails = [];
                foreach($rows as $row){
                    $logId = $row['practiceDailyPaper']['id'];
                    $resDatails = Http::withHeaders($mergedHeaders)
                                        ->get($this->apiUrl->getLogDatailUrl($logId));
                    $allDatails[] = $resDatails->json();
                }
                foreach($allDatails as &$detail) {
                    if(isset($detail['data'])) {
                        if(isset($detail['data']['fileList'])){
                            foreach($detail['data']['fileList'] as &$file){
                                $file['filePath'] = ApiUrl::$baseApiUrl . $file['filePath'];
                            }
                        }
                    }
                }
                $mergedDatails = [
                    'data' => $data,
                    'datails'=> $allDatails,
                ];

                // 将数据存入Redis，设置7天过期
                Redis::setex($cacheKey.':'.Auth::id(), 60, json_encode($mergedDatails));
                Log::info('放置Key:'.$cacheKey.':'.Auth::id());
                return ResponsePojo::success(HttpStatus::OK,HttpStatus::getStatusMessage(HttpStatus::OK), $mergedDatails);
            }
    }



}